<?php
namespace App\Services\SysRbac;

use App\Models\SysMenu;
use App\Models\SysMenuGroup;
use App\Services\Tool\TreeService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;

/**
 * 菜单服务类
 * @package App\Services
 */
class SysMenuService
{
    /**
     * 构造函数
     */
    public function __construct()
    {

    }

    /**
     * 获取分组列表
     */
    public function getGroupList()
    {
        $groupList = SysMenuGroup::all();
        return $groupList;
    }

    /**
     * 获取分组数据
     * @param $groupId
     * @return mixed
     */
    public function getGroupData($groupId)
    {
        return SysMenuGroup::findOrFail($groupId);
    }

    /**
     * 通过key获取分组数据
     * @param $key
     * @return mixed
     */
    public function getGroupDataByKey($key)
    {
        return SysMenuGroup::where('group_key', $key)->first()->toArray();
    }
    /**
     * 保存数据
     * @param Request $request
     * @return bool
     */
    public function saveGroup(Request $request)
    {
        if ($request->group_id){
            $menuGroup = SysMenuGroup::find($request->group_id);
        }else{
            $menuGroup = new SysMenuGroup;
        }
        $menuGroup->group_key = $request->group_key;
        $menuGroup->group_name = $request->group_name;
        return $menuGroup->save();
    }

    /**
     * 删除模型
     * @param $groupId
     * @return mixed
     */
    public function delGroup($groupId)
    {
        $menuGroup = SysMenuGroup::find($groupId);
        return $menuGroup->delete();
    }

    /**
     * 获取菜单列表
     * @param $groupId
     * @return mixed
     */
    public function getMenuList($groupId)
    {
        $menuList = SysMenu::where('group_id', $groupId)->orderBy('order_num','ASC')->orderBy('menu_id','ASC')->get()->toArray();
        $newMenuList = [];
        foreach ($menuList as $v){
            $newMenuList[(int)$v['menu_id']] = $v;
        }
        return $newMenuList;
    }

    /**
     * 回去菜单数据
     * @param $menuId
     * @return mixed
     */
    public function getMenuData($menuId)
    {
        $menuData = SysMenu::find($menuId);
        return $menuData;
    }

    /**
     * 通过分组key获取菜单列表
     */
    public function getCacheMenuListByGroupKey($key)
    {
        $cacheKey = 'cms_sysmenu_menulistbygroupkey_'.$key;
        //Cache::delete($cacheKey);
        $cacheData = Cache::get($cacheKey);
        if (!$cacheData){
            $groupData = $this->getGroupDataByKey($key);
            if ($groupData){
                $cacheData = Db::table('sys_menus')
                    ->leftJoin('sys_permissions','sys_menus.perm_id','=','sys_permissions.perm_id')
                    ->select('sys_menus.*','sys_permissions.name as perm_name','sys_permissions.is_public')
                    ->whereNull('sys_menus.deleted_at')
                    ->orderBy('sys_menus.order_num','ASC')->orderBy('sys_menus.menu_id','ASC')
                    ->get()->map(function ($value) {
                        return (array)$value;
                    })->toArray();
                if ($cacheData){
                    foreach ($cacheData as $k => $v){
                        if ($v['route_params']){
                            $route_params = json_decode($v['route_params'], true);
                            $cacheData[$k]['route_params'] = $route_params;
                        }else{
                            $cacheData[$k]['route_params'] = [];
                        }
                    }
                }
                Cache::put($cacheKey, $cacheData, 60);
            }
        }
        return $cacheData;
    }

    /**
     * 清除用户菜单缓存
     * @param $groupId
     * @return bool
     */
    public function clearMenuListCache($groupId)
    {
        $groupData = $this->getGroupData($groupId);
        if (empty($groupData)){
            return false;
        }
        $cacheKey = 'cms_sysmenu_menulistbygroupkey_'.$groupData->group_key;
        return Cache::delete($cacheKey);
    }
    /**
     * 保存菜单数据
     * @param $request
     * @return bool
     */
    public function saveMenu($request)
    {
        if ($request->menu_id){
            $menuModel = SysMenu::find($request->menu_id);
        }else{
            $menuModel = new SysMenu();
        }
        $menuModel->group_id = $request->input('group_id', 0);
        $menuModel->parent_id = $request->input('parent_id', 0);
        $menuModel->menu_name = $request->input('menu_name', '');
        $menuModel->perm_id = $request->input('perm_id', 0);
        //路由参数
        $route_params = $request->input('route_params', '');
        parse_str($route_params, $route_params);
        $route_params = $route_params ? $route_params : [];
        $menuModel->route_params = $route_params;
        $menuModel->description = (string) $request->input('description','');
        $menuModel->icon_class = (string) $request->input('icon_class', '');
        $menuModel->order_num = (int) $request->input('order_num', 0);
        $rs = $menuModel->save();
        //清除缓存
        $this->clearMenuListCache($menuModel->group_id);
        return $rs;
    }

    /**
     * 删除菜单
     * @param array $menuIds
     * @return int
     */
    public function del($menuIds = [])
    {
        $menuModel = SysMenu::find($menuIds);
        if (empty($menuModel)){
            throw new \Exception('菜单不存在');
        }
        $rs = $menuModel->delete();
        //清除缓存
        $rs && $this->clearMenuListCache($menuModel->first()->group_id);
        return $rs;
    }

    /**
     * 获取菜单所有路由名称列表
     * @param $key
     * @return array|mixed
     */
    public function getMenuRouteList($key)
    {
        $menuList = $this->getCacheMenuListByGroupKey($key);
        $routeList = [];
        if ($menuList){
            foreach ($menuList as $v){
                if ($v['perm_name']){
                    $routeList[] = $v['perm_name'];
                }
            }
        }
        return $routeList;
    }
    /**
     * 获取有权限的菜单列表
     * @param $key
     * @return array|mixed
     */
    public function getHasPermTreeMenuList($key)
    {
        $menuList = $this->getCacheMenuListByGroupKey($key);
        if ($menuList){
            foreach ($menuList as $k => $v){
                if ($v['perm_name'] && (!Route::has($v['perm_name']) || Gate::denies($v['perm_name']))){
                    unset($menuList[$k]);
                }
            }
            $menuList = array_values($menuList);
        }
        $tree = new TreeService('menu_id','parent_id', 'child');
        $tree->load($menuList);
        $treelist = $tree->deepTree();
        return $treelist;
    }
}